package edu.xhu.im.processor;

import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson2.JSON;
import edu.xhu.im.server.UserChannelCtxMap;
import edu.xhu.model.common.constants.kafka.topic.ChatTopic;
import edu.xhu.model.im.enums.IMCmdType;
import edu.xhu.model.im.enums.IMSendCode;
import edu.xhu.model.im.pojos.IMRecvInfo;
import edu.xhu.model.im.pojos.IMSendInfo;
import edu.xhu.model.im.pojos.IMSendResult;
import edu.xhu.model.im.pojos.IMUserInfo;
import io.netty.channel.ChannelHandlerContext;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Component;

import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@Component
@RequiredArgsConstructor
public class ReadedMessageProcessor extends AbstractMessageProcessor<IMRecvInfo> {

    private final StringRedisTemplate redisTemplate;

    private final KafkaTemplate<String, String> kafkaTemplate;

    @Override
    public void process(IMRecvInfo recvInfo) {
        IMUserInfo sender = recvInfo.getSender();
        IMUserInfo receiver = recvInfo.getReceivers().get(0);
        log.info("接收到消息，发送者:{},接收者:{}，内容:{}", sender.getId(), receiver.getId(), recvInfo.getData());
        try {
            ChannelHandlerContext channelCtx = UserChannelCtxMap.getChannelCtx(receiver.getId(), 0);
            //如果用户在线,直接刷新
            if (channelCtx != null) {
                // 推送消息到用户
                IMSendInfo<Object> sendInfo = new IMSendInfo<>();
                sendInfo.setCmd(recvInfo.getCode());
                sendInfo.setData(recvInfo.getData());
                channelCtx.channel().writeAndFlush(sendInfo);
                // 异步刷新标志位
                sendResult(recvInfo, IMSendCode.SUCCESS);
            }
            //用户不在线..异步刷新标志位就行了
            else {
                // 异步刷新标志位
                sendResult(recvInfo, IMSendCode.NOT_ONLINE);
                log.error("未找到channel,对方不在线，发送者:{},接收者:{}，内容:{}", sender.getId(), receiver.getId(), recvInfo.getData());
            }
        } catch (Exception e) {
            // 消息推送失败确认
            sendResult(recvInfo, IMSendCode.UNKONW_ERROR);
            log.error("发送异常，发送者:{},接收者:{}，内容:{}", sender.getId(), receiver.getId(), recvInfo.getData(), e);
        }

    }

    private void sendResult(IMRecvInfo recvInfo, IMSendCode sendCode) {
        if (recvInfo.getSendResult()) {
            IMRecvInfo recallInfo = new IMRecvInfo();
            //只要id,sender,receiver,code
            recallInfo.setDetailId(recvInfo.getDetailId())
                    .setSender(recvInfo.getSender())
                    .setReceivers(recvInfo.getReceivers());
            recallInfo.setCode(sendCode.code());
            //看是否是离线,离线需要data
            if (recvInfo.getDetailId() == null) {
                recallInfo.setData(recvInfo.getData());
            }
            // 发消息给kafka处理
            kafkaTemplate.send(ChatTopic.BILL_CHAT_READED_PROCESS, JSON.toJSONString(recallInfo));
        }
    }

    @Override
    public IMRecvInfo transForm(Object o) {
        log.info("o是:{}", o);
        IMRecvInfo imRecvInfo = null;
        try {
            imRecvInfo = buildIMRecvInfo(o);
        } catch (Exception e) {
            log.error("转换出错:{}", e.toString());
        }
        return imRecvInfo;
    }

    private IMRecvInfo buildIMRecvInfo(Object o) {
        //1.得到总的map
        Map<String, Object> imrMap = (LinkedHashMap) o;
        //2.构建返回值info
        IMRecvInfo info = new IMRecvInfo();
        info.setCmd((Integer) imrMap.get("cmd"));
        info.setSendResult((Boolean) imrMap.get("sendResult"));
        info.setServiceName(imrMap.get("serviceName").toString());
        //3.构建sender
        Map<String, Object> imUserInfoMap = (LinkedHashMap) imrMap.get("sender");
        IMUserInfo imUserInfo = new IMUserInfo();
        imUserInfo.setId(Long.valueOf(imUserInfoMap.get("id").toString()));
        imUserInfo.setTerminal((Integer) imUserInfoMap.get("terminal"));
        //4.得到所有receivers
        Object o1 = imrMap.get("receivers");
        List<Map<String, Object>> receiversMaps = (List<Map<String, Object>>) o1;
        //5.构建receivers
        List<IMUserInfo> collect = receiversMaps.stream().map(map -> {
            IMUserInfo info1 = new IMUserInfo();
            info1.setId(Long.valueOf(map.get("id").toString()));
            info1.setTerminal((Integer) map.get("terminal"));
            return info1;
        }).collect(Collectors.toList());
        info.setSender(imUserInfo);
        info.setReceivers(collect);
        //6.构建消息,data
        Map<String, Object> data = (LinkedHashMap) imrMap.get("data");
        info.setData(data);
        return info;
    }
}
